package util

import (
	"errors"
	"sync"
)

const (
	step = 500
)

type mysqlIdGenerate struct {
	lock   sync.RWMutex
	lastId uint32
	start  uint32
}

func (i *mysqlIdGenerate) GetId() (uint32, error) {
	// 判断当前id库存是否需要去申请
	if (i.lastId - i.start) < (step * 0.1) {
		// 申请id
		i.apply()
	}
	i.lock.RLock()
	defer i.lock.RUnlock()
	if i.start >= i.lastId {
		return 0, errors.New("id申请异常")
	}
	i.start++
	return i.start, nil
}

func (i *mysqlIdGenerate) apply() (uint32, error) {
	i.lock.Lock()
	defer i.lock.Unlock()
	var err error
	retry := 0
	var lockResult bool
	for {
		if retry > 3 {
			break
		}
		lockResult, err = Lock("id:gen", func() {
			var result int64
			result = GetRedis().IncrBy("id:gen", step).Val()
			println(result)
			i.lastId = uint32(result)
			i.start = uint32(result - step)
		})
		if lockResult {
			break
		}
		retry++
	}
	return i.start, err
}
